package com.zenith.storage.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zenith.common.result.PageResult;
import com.zenith.common.util.JwtUtil;
import com.zenith.common.util.UserContextUtil;
import com.zenith.storage.mapper.StorageFolderMapper;
import com.zenith.storage.mapper.StorageUserFileMapper;
import com.zenith.storage.po.domain.StorageFolder;
import com.zenith.storage.po.domain.StorageUserFile;
import com.zenith.storage.service.NetDiskService;
import com.zenith.storage.po.dto.FolderDTO;
import com.zenith.storage.po.dto.FolderFileQueryDTO;
import com.zenith.storage.po.dto.MoveFileDTO;
import com.zenith.storage.po.dto.RenameDTO;
import com.zenith.storage.po.vo.FolderFileVO;
import com.zenith.storage.po.vo.FolderVO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 网盘功能服务实现类
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class NetDiskServiceImpl extends ServiceImpl<StorageFolderMapper, StorageFolder> implements NetDiskService {

    @Autowired
    private StorageFolderMapper storageFolderMapper;
    @Autowired
    private StorageUserFileMapper storageUserFileMapper;
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public FolderVO createFolder(FolderDTO folderDTO) {
        // 查询父目录
        StorageFolder parentFolder = null;
        if (folderDTO.getParentId() != 0) {
            parentFolder = storageFolderMapper.selectById(folderDTO.getParentId());
            if (parentFolder == null) {
                throw new RuntimeException("父目录不存在");
            }
        }
        
        // 构造完整路径
        String fullPath = folderDTO.getFolderName();
        if (parentFolder != null) {
            fullPath = parentFolder.getFullPath() + "/" + folderDTO.getFolderName();
        }
        
        // 检查同名文件夹是否已存在
        StorageFolder existingFolder = storageFolderMapper.selectOne(
                new LambdaQueryWrapper<StorageFolder>()
                        .eq(StorageFolder::getUserId, UserContextUtil.getCurrentUserId())
                        .eq(StorageFolder::getParentId, folderDTO.getParentId())
                        .eq(StorageFolder::getFolderName, folderDTO.getFolderName())
                        .eq(StorageFolder::getStatus, 1));
        
        if (existingFolder != null) {
            throw new RuntimeException("同名文件夹已存在");
        }
        
        // 创建文件夹
        StorageFolder folder = new StorageFolder();
        folder.setUserId(UserContextUtil.getCurrentUserId());
        folder.setParentId(folderDTO.getParentId());
        folder.setFolderName(folderDTO.getFolderName());
        folder.setFullPath(fullPath);
        folder.setLevel(parentFolder == null ? 0 : parentFolder.getLevel() + 1);
        folder.setStatus(1);
        
        storageFolderMapper.insert(folder);
        
        // 转换为VO对象
        return convertToVO(folder);
    }
    
    @Override
    public List<FolderVO> getFolderTree(Long userId) {
        // 查询用户的所有文件夹
        List<StorageFolder> folders = storageFolderMapper.selectList(
                new LambdaQueryWrapper<StorageFolder>()
                        .eq(StorageFolder::getUserId, userId)
                        .eq(StorageFolder::getStatus, 1)
                        .orderByAsc(StorageFolder::getLevel));
        
        // 构造文件夹树
        return buildFolderTree(folders, 0L);
    }
    
    @Override
    public PageResult<FolderFileVO> getFolderFiles(FolderFileQueryDTO queryDTO) {
        // 查询文件夹中的文件和子文件夹
        LambdaQueryWrapper<StorageUserFile> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(StorageUserFile::getUserId, queryDTO.getUserId());
        queryWrapper.eq(StorageUserFile::getFolderId, queryDTO.getFolderId());
        
        if (StringUtils.hasText(queryDTO.getKeyword())) {
            queryWrapper.like(StorageUserFile::getFileName, queryDTO.getKeyword());
        }
        
        if (queryDTO.getOnlyFolder() != null && queryDTO.getOnlyFolder()) {
            queryWrapper.eq(StorageUserFile::getIsDir, 1);
        }
        
        // 分页查询
        IPage<StorageUserFile> page = new Page<>(queryDTO.getPageNum(), queryDTO.getPageSize());
        IPage<StorageUserFile> result = storageUserFileMapper.selectPage(page, queryWrapper);
        
        // 转换为VO列表
        List<FolderFileVO> folderFileVOList = result.getRecords().stream()
                .map(this::convertToFolderFileVO)
                .collect(Collectors.toList());
        
        return PageResult.ofPage(queryDTO.getPageNum(), queryDTO.getPageSize(), result.getTotal(), folderFileVOList);
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean moveFile(MoveFileDTO moveFileDTO) {
        StorageUserFile userFile = storageUserFileMapper.selectById(moveFileDTO.getFileId());
        if (userFile == null) {
            throw new RuntimeException("文件不存在");
        }
        
        // 更新文件夹ID
        userFile.setFolderId(moveFileDTO.getTargetFolderId());
        return storageUserFileMapper.updateById(userFile) > 0;
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean rename(RenameDTO renameDTO) {
        if (renameDTO.getIsDir()) {
            // 重命名文件夹
            StorageFolder folder = storageFolderMapper.selectById(renameDTO.getId());
            if (folder == null) {
                throw new RuntimeException("文件夹不存在");
            }
            
            // 更新文件夹名称
            folder.setFolderName(renameDTO.getNewName());
            return storageFolderMapper.updateById(folder) > 0;
        } else {
            // 重命名文件
            StorageUserFile userFile = storageUserFileMapper.selectById(renameDTO.getId());
            if (userFile == null) {
                throw new RuntimeException("文件不存在");
            }
            
            // 更新文件名称
            userFile.setFileName(renameDTO.getNewName());
            return storageUserFileMapper.updateById(userFile) > 0;
        }
    }
    
    /**
     * 构造文件夹树
     * @param folders 文件夹列表
     * @param parentId 父ID
     * @return 文件夹树
     */
    private List<FolderVO> buildFolderTree(List<StorageFolder> folders, Long parentId) {
        List<FolderVO> tree = new ArrayList<>();
        
        for (StorageFolder folder : folders) {
            if (folder.getParentId().equals(parentId)) {
                FolderVO folderVO = convertToVO(folder);
                folderVO.setChildren(buildFolderTree(folders, folder.getId()));
                tree.add(folderVO);
            }
        }
        
        return tree;
    }
    
    /**
     * 将StorageFolder转换为FolderVO
     * @param folder StorageFolder对象
     * @return FolderVO对象
     */
    private FolderVO convertToVO(StorageFolder folder) {
        FolderVO folderVO = new FolderVO();
        folderVO.setId(folder.getId());
        folderVO.setParentId(folder.getParentId());
        folderVO.setFolderName(folder.getFolderName());
        folderVO.setFullPath(folder.getFullPath());
        folderVO.setLevel(folder.getLevel());
        folderVO.setSortOrder(folder.getSortOrder());
        folderVO.setCreateTime(folder.getCreateTime());
        return folderVO;
    }
    
    /**
     * 将StorageUserFile转换为FolderFileVO
     * @param userFile StorageUserFile对象
     * @return FolderFileVO对象
     */
    private FolderFileVO convertToFolderFileVO(StorageUserFile userFile) {
        FolderFileVO folderFileVO = new FolderFileVO();
        folderFileVO.setId(userFile.getId());
        folderFileVO.setName(userFile.getFileName());
        folderFileVO.setIsDir(userFile.getIsDir() == 1);
        folderFileVO.setUpdateTime(userFile.getUpdateTime());
        return folderFileVO;
    }
}